﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.IO;
using Ivi.Visa.Interop;
using System.Collections.Generic;
using _XYOTA;
using static _XYOTA.WorkFlag;
using System.Reflection;
using System.Text;



namespace _015串口助手
{
   

    public partial class Main : Form
    {
        Sunisoft.IrisSkin.SkinEngine s3;
        
        public Main()
        {
            InitializeComponent();
            s3 = new Sunisoft.IrisSkin.SkinEngine();
            s3.SkinAllForm = true;
        }

        //全局变量
        public class MyGlobal
        {
            //升级的文件相关
            public static int File_size = 0;        //升级文件的大小
            public static int ToUpdateFlag = 0;      //0停止状态  1开始升级标志  2正在接收数据状态
        }
        public class Receive
        {
            public static byte[] buff = new byte[1000];
            public static int len = 0;
        }
        public class Trans
        {
            public static byte[] buff = new byte[1000];
            public static int len = 0;
        }

        public class UsartAndFile
        {
            public static bool Open = false;
            public static bool fileopen = false;
        }

 

        /// <summary>
        /// 主窗口参数初始化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
                WorkFlag workFlag = new WorkFlag();
                CheckForIllegalCrossThreadCalls = false;
                s3.SkinFile = Application.StartupPath + @"\Skins\MacOS.ssk";
                Control.CheckForIllegalCrossThreadCalls = false;
                comboBox2.Text = "115200";
                toolStripButton2.Enabled = true;
                toolStripButton3.Enabled = false;
                foreach (string portname in SerialPort.GetPortNames())
                {
                    comboBox1.Items.Add(portname);
                }
                label2.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "lightL.ico");
                timer1.Enabled = true;
                toolStripStatusLabel5.Text = System.DateTime.Now.ToLocalTime().ToString();
                for (int i = 0; i < workFlag.Skintype.Length; i++)
                {
                    toolStripComboBox2.Items.Add(workFlag.Skintype[i]);
                }
                toolStripComboBox2.SelectedItem = 2;
                UsartAndFile.Open = false;
                UsartAndFile.fileopen = false;
            }
            catch (Exception)
            { MessageBox.Show("启动失败,请重启"); }
        }
        

        #region  串口数据发送函数  
        public void SerialPortSendData(byte[] orderbuff, int orderbuff_len)
        {
            try
            {
                /* 串口打开就发送 */
                if (UsartAndFile.Open == true && UsartAndFile.fileopen == true)
                {
                    /* 检查发送的数据是否为空 */
                    if (orderbuff_len == 0)
                    {
                        MessageBox.Show("发送数据不正确");
                        return;
                    }
                    serialPort1.Write(orderbuff, 0, orderbuff_len);
                }
                else
                {
                    MessageBox.Show("串口出现问题");
                    button_Update.Text = "升级";
                    button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
                    MyGlobal.ToUpdateFlag = 0;
                    //serialPort1.Close();
                }
            }
            catch (Exception)
            {  }
            
        }
        #endregion

    

        #region 选择升级文件
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog fileName = new OpenFileDialog();
                fileName.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                fileName.Filter = "(*.bin)|*.bin|(*.txt)|*.txt|(*.hex)|*.hex";
                fileName.FilterIndex = 0;
                fileName.RestoreDirectory = true;
                if (fileName.ShowDialog() == DialogResult.OK)
                {
                    string Path = fileName.FileName.ToString();
                    string Name = Path.Substring(Path.LastIndexOf("\\") + 1);
                    textBox_File.Text = Path;
                }
                UsartAndFile.fileopen = true;
                //获取升级文件
                FileStream F = new FileStream(fileName.FileName.Trim().ToString(), FileMode.Open, FileAccess.Read);
                MyGlobal.File_size =(int) F.Length;
                F.Close();
                if (MyGlobal.File_size >= 120000)
                {

                    if (this.IsHandleCreated)
                    {
                        Invoke(new Action(() =>
                        {
                            richTextBox_debug1.Clear();
                            richTextBox_debug1.Text += ">文件大小:"+ MyGlobal.File_size.ToString()+"Bytes 超限!最大支持bin文件120K!\r\n";
                            richTextBox_debug1.Text += ">请重新选择！\r\n";
                            richTextBox_debug1.Select(richTextBox_debug1.TextLength, 0);
                            richTextBox_debug1.ScrollToCaret();
                        }));
                    }

                }
                else {

                    if (this.IsHandleCreated)
                    {
                        Invoke(new Action(() =>
                        {
                            richTextBox_debug1.Clear();
                            richTextBox_debug1.Text += ">文件大小:";
                            richTextBox_debug1.Text += MyGlobal.File_size.ToString();
                            richTextBox_debug1.Text += " Bytes\n";
                            richTextBox_debug1.Select(richTextBox_debug1.TextLength, 0);
                            richTextBox_debug1.ScrollToCaret();
                        }));
                    }
                }
               
                //进度条显示
                for (int i = 0; i < 100; i++)
                {
                    progressBar1.Value = i;
                    Thread.Sleep(5);
                }
                DialogResult result = MessageBox.Show("加载完成", "Information", MessageBoxButtons.OK);
                if (result == DialogResult.OK)
                {
                    progressBar1.Value = 0;
                }
            }
            catch (Exception)
            {
                UsartAndFile.fileopen = false;
                MessageBox.Show("打开失败请重试！");   
            }
            
        }
        #endregion

        #region 开始升级
        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                if (false == UsartAndFile.Open)
                { MessageBox.Show("请打开串口", "提示", MessageBoxButtons.OK); return; }
                if (UsartAndFile.fileopen == false)
                { MessageBox.Show("请选择文件", "提示", MessageBoxButtons.OK); return; }
                //开始执行升级操作
                if (button_Update.Text.Trim() == "停止")
                {
                    button_Update.Text = "升级";
                    button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
                    MyGlobal.ToUpdateFlag = 0;
                    //serialPort1.Close();
    
                }
                else if (button_Update.Text.Trim() == "升级")
                {
 
                    button_Update.Text = "停止";
                    button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLD.gif");

                    ////线程相关:打开升级线程
                    ThreadStart childref = new ThreadStart(Thread_update);
                    Thread childThread = new Thread(childref);
                    if (childThread.IsAlive==false)
                    {
                        childThread.Start();
                    }
                   

                }
            }
            catch (Exception)
            {            }
        }
        #endregion

        #region  升级发送线程
        public void Thread_update()
        {
            //获取文件
            string r_path = textBox_File.Text.Trim();
            try
            {
            //获取升级文件
            FileStream F = new FileStream(r_path, FileMode.Open, FileAccess.Read);//打开文件
            MyGlobal.File_size =(int) F.Length;
            byte[] tmp = new byte[MyGlobal.File_size];
            F.Read(tmp, 0, MyGlobal.File_size);
            F.Close();
            if (MyGlobal.File_size>=120000)
            {
                    MessageBox.Show("文件大小超限,请重新选择","提示", MessageBoxButtons.OK);
                    button_Update.Text = "升级";
                    button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
                    MyGlobal.ToUpdateFlag = 0;
                    return;
            }
               //发送包头
            int time = 0;
            MyGlobal.ToUpdateFlag = 1;
            setDebugText(">开始升级...\r\n");
            while (MyGlobal.ToUpdateFlag == 1)
            {
                time++;
                //发送升级帧头
                char[] start = { 'S', 'T', 'A', 'R', 'T' };
                SerialPortSendData(tmp, start.Length);
                Thread.Sleep(1000);
                setDebugText(">文件大小:" + MyGlobal.File_size.ToString() + " Bytes\n");
                setDebugText(">初次等待回复:" + time.ToString() + " 次.....\r\n");
                if (time > 15)//连续发送还没有收到有效回复就认为下位机无响应
                {
                    setDebugText(">>升级失败:帧头无响应！！！\r\n");
                    button_Update.Text = "升级";
                    button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
                    MyGlobal.ToUpdateFlag = 0;
                    return;
                }  
            }
             if (MyGlobal.ToUpdateFlag == 0) { setDebugText(">停止升级！\r\n"); return; }

              //再次发送包头
              time = 0;
              MyGlobal.ToUpdateFlag = 1;
              while (MyGlobal.ToUpdateFlag == 1)
              {
                  time++;
                  //发送升级帧头
                  char[] start = { 'S', 'T', 'A', 'R', 'T' };
                  SerialPortSendData(tmp, start.Length);
                  Thread.Sleep(1000);
                  setDebugText(">文件大小:" + MyGlobal.File_size.ToString() + " Bytes\n");
                  setDebugText(">再次等待回复:" + time.ToString() + " 次.....\r\n");
                  if (time > 15)//连续发送还没有收到有效回复就认为下位机无响应
                  {
                      setDebugText(">>升级失败:帧头无响应！！！\r\n");
                      button_Update.Text = "升级";
                      button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
                      MyGlobal.ToUpdateFlag = 0;
                      return;
                  }
              }
            if (MyGlobal.ToUpdateFlag == 0) { setDebugText(">停止升级！\r\n"); return; }
            setDebugText(">收到回复!!!开始下发升级文件...\r\n");
            time = 0;
            MyGlobal.ToUpdateFlag = 1;
            while (MyGlobal.ToUpdateFlag == 1)
            {
                time++;
                //发送命令阶段
                SerialPortSendData(tmp, MyGlobal.File_size);
                Thread.Sleep(2000);
                setDebugText(">下发文件次数:" + time.ToString() + "......\n");
                if (time > 10)//连续发送还没有收到有效回复就认为下位机无响应
                {
                
                  if (this.IsHandleCreated)
                   {
                      setDebugText(">>升级失败:文件无响应\r\n");
                      button_Update.Text = "升级";
                      button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
                      MyGlobal.ToUpdateFlag = 0; 
                   }
                   return;
                }
            }
            if (MyGlobal.ToUpdateFlag == 0)
            {
                setDebugText(">停止升级！\r\n");
            }
            else
            {
                setDebugText(">> 升级成功 ! ! !\r\n");
                button_Update.Text = "升级";
                button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
            }
            }
            catch (Exception)
             {
               setDebugText(">文件打开错误!!!\r\n");
               button_Update.Text = "升级";
               button_Update.Image = Image.FromFile(Application.StartupPath + @"\Skins\" + "CLJ.png");
               MyGlobal.ToUpdateFlag = 0;
               return;
            }
    }
     #endregion


        /// <summary>
        /// 串口数据接收
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] recbuffer;
            try
            {
                recbuffer = new byte[serialPort1.BytesToRead];
                serialPort1.Read(recbuffer, 0, recbuffer.Length);
                switch (recbuffer.Length)
                {
                    case 5://收到升级头回复
                        if (recbuffer[0] != 'S') return;
                        if (recbuffer[1] != 'T') return;
                        if (recbuffer[2] != 'A') return;
                        if (recbuffer[3] != 'R') return;
                        if (recbuffer[4] != 'T') return;
                        MyGlobal.ToUpdateFlag = 2;
                        break;
                    case 6://收到app文件回复
                        if (recbuffer[0] != 'F') return;
                        if (recbuffer[1] != 'I') return;
                        if (recbuffer[2] != 'L') return;
                        if (recbuffer[3] != 'E') return;
                        if (recbuffer[4] != 'O') return;
                        if (recbuffer[5] != 'K') return;
                        MyGlobal.ToUpdateFlag = 2;//
                        break;
                    default:
                        richTextBox_debug1.AppendText(Encoding.UTF8.GetString(recbuffer));
                        break;
                }
            }
            catch (Exception)
            { }
        }

        /// <summary>
        /// 换肤
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripComboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                string Skinname = toolStripComboBox2.SelectedItem.ToString().Trim() + ".ssk";
                s3.SkinFile = Application.StartupPath + @"\Skins\" + Skinname;
            }
            catch (Exception)
            { }
        }

        /// <summary>
        /// 清除所有信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            richTextBox_debug1.Clear();
        }

        /// <summary>
        /// 打开串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            try
            {
                serialPort1.PortName = comboBox1.Text;
                serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
                serialPort1.Open();
                toolStripButton2.Enabled = false;
                toolStripButton3.Enabled = true;
                //使用资源文件里的资源
                var file = _XYOTA.Properties.Resources.ResourceManager.GetObject("lightH");
                label2.Image = (System.Drawing.Image)file;
                UsartAndFile.Open = true;
                comboBox1.Enabled = false;
            }
            catch (Exception)
            {
                MessageBox.Show("端口错误，请检查串口！");
                UsartAndFile.Open = false;
            }
        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            try
            {
                serialPort1.Close();
                toolStripButton2.Enabled = true;
                toolStripButton3.Enabled = false;
                var file = _XYOTA.Properties.Resources.ResourceManager.GetObject("lightL");
                label2.Image = (System.Drawing.Image)file;
                UsartAndFile.Open = false;
                comboBox1.Enabled = true;
            }
            catch (Exception)
            {
                MessageBox.Show("端口错误，请检查串口！");
            }
        }

        /// <summary>
        /// 每次单击端口号下拉框 自动更新所有端口号
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBox1_Click(object sender, EventArgs e)
        {

            //移除所有端口后再添加这样每次点击都能保证端口都是最新列表
            comboBox1.Items.Clear();
            //添加新的端口
            foreach (string portname in SerialPort.GetPortNames())
            {
                comboBox1.Items.Add(portname);
            }
        }

        /// <summary>
        /// 联系方式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 联系方式_Click(object sender, EventArgs e)
        {
            MessageBox.Show("获取源码请联系QQ:1458356834\n");
        }

        /// <summary>
        /// 显示系统时间
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer1_Tick(object sender, EventArgs e)
        {
            toolStripStatusLabel5.Text = System.DateTime.Now.ToLocalTime().ToString();
        }

        /// <summary>
        /// 显示通信协议界面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            通信协议 Trans = new 通信协议();
            // Trans.ShowDialog();
            Trans.Show();
        }

        /// <summary>
        /// 设置Debug文本
        /// </summary>
        /// <param name="str"></param>
        private void setDebugText(string str)
        {
            if (this.IsHandleCreated)
            {
                Invoke(new Action(() =>
                {
                    richTextBox_debug1.Text += str;
                    richTextBox_debug1.Select(richTextBox_debug1.TextLength, 0);
                    richTextBox_debug1.ScrollToCaret();
                    return;
                }));
            }
        }
 


    }
}
